#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>

#define MAX_SIZE 100
#define NUM_THREADS 4 // 假设线程数量

typedef struct {
    int t_id; // 线程 ID
    pthread_barrier_t *barrier_Division;
    pthread_barrier_t *barrier_Elimination;
    double (*A)[MAX_SIZE];
    int n;
} ThreadParam_t;

double A[MAX_SIZE][MAX_SIZE]; // 假设 A 是全局变量
int n; // 假设 n 是全局变量

void *threadFunc(void *param) {
    ThreadParam_t *p = (ThreadParam_t *)param;
    int t_id = p->t_id;
    pthread_barrier_t *barrier_Division = p->barrier_Division;
    pthread_barrier_t *barrier_Elimination = p->barrier_Elimination;
    double (*A)[MAX_SIZE] = p->A;
    int n = p->n;

    struct timespec start, end;
    clock_gettime(CLOCK_MONOTONIC, &start);

    for (int k = 0; k < n; ++k) {
        // 等待主线程完成除法操作
        pthread_barrier_wait(barrier_Division);
        
        // t_id 为 0 的线程进行除法操作
        if (t_id == 0) {
            for (int j = k + 1; j < n; ++j) {
                A[k][j] = A[k][j] / A[k][k];
            }
        }

        // 等待所有线程完成除法操作
        pthread_barrier_wait(barrier_Division);
        
        // 等待主线程完成消去操作
        pthread_barrier_wait(barrier_Elimination);
        
        // 进行消去操作
        for (int i = k + 1; i < n; ++i) {
            for (int j = k + 1; j < n; ++j) {
                A[i][j] = A[i][j] - A[i][k] * A[k][j];
            }
            A[i][k] = 0.0;
        }

        // 等待所有线程完成消去操作
        pthread_barrier_wait(barrier_Elimination);
    }

    clock_gettime(CLOCK_MONOTONIC, &end);

    long long seconds = end.tv_sec - start.tv_sec;
    long long ns = end.tv_nsec - start.tv_nsec;
    if (start.tv_nsec > end.tv_nsec) { // 如果开始的时间小于结束的时间
        --seconds;
        ns += 1000000000;
    }
    double elapsed = seconds + ns * 1e-9;
    printf("Thread %d execution time: %f seconds\n", t_id, elapsed);

    pthread_exit(NULL);
}

int main() {
    pthread_barrier_t barrier_Division, barrier_Elimination;
    pthread_barrier_init(&barrier_Division, NULL, NUM_THREADS);
    pthread_barrier_init(&barrier_Elimination, NULL, NUM_THREADS);

    pthread_t threads[NUM_THREADS];
    ThreadParam_t params[NUM_THREADS];
    for (int t_id = 0; t_id < NUM_THREADS; ++t_id) {
        params[t_id].t_id = t_id;
        params[t_id].barrier_Division = &barrier_Division;
        params[t_id].barrier_Elimination = &barrier_Elimination;
        params[t_id].A = A;
        params[t_id].n = n;
        pthread_create(&threads[t_id], NULL, threadFunc, &params[t_id]);
    }

    for (int t_id = 0; t_id < NUM_THREADS; ++t_id) {
        pthread_join(threads[t_id], NULL);
    }

    pthread_barrier_destroy(&barrier_Division);
    pthread_barrier_destroy(&barrier_Elimination);

    return 0;
}
